package com.wan.javanew;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * java8 函数式接口
 * 每一个lambda表达式可以看作一个类型 通常称接口类型
 * 而 函数式接口 是指仅仅包含一个抽象方法的接口 每一个该类型的lambda表达式
 * 都会匹配到这个抽象方法 因为默认方法 不算抽象方法 可以多定义默认方法
 *
 * 我们可以将lambda表达式当作任意只包含一个抽象方法的接口类型
 * 为确保接口只有一个抽象方法 可以加@FunctionalInterface 注解修饰
 *
 *
 *
 *
 *
 */
@FunctionalInterface
public interface JavaNewMetodInterface<T,I> {
    I parse(T value);
    default Integer add(Integer a, Integer b){
        return a+b;
    }
}

class JavaTest{
    public static void main(String[] args) {
        //接口类型的 method 直接调用 接口的方法
        //等号后面的 相当于要实现的方法体
        JavaNewMetodInterface<Date,String> method = (str) ->{
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String string = format.format(str);
            return string;
        };
        String string = method.parse(new Date());
        System.out.println(string);
        Integer sum = method.add(1,2);
        System.out.println(sum);

        JavaNewMetodInterface<String,Integer> metodInterface = (param) ->{
            Integer suma =  Integer.parseInt(param);
            return suma;
        };
        Integer param = metodInterface.parse("1");
        System.out.println(param);
    }
}
/**
 * lambda表达式 ::关键字引用 构造函数
 * lambda表达式 的作用域 可以直接访问外层用final修饰的局部变量
 * 跟以往不同的是 外层局部变量也可以不用final修饰 是不会报错的
 * 但是后面 改变了局部变量的值编译会报错 隐性final
 * lambda表达式内部对于实例字段和静态变量可读可写跟匿名对象一致
 */
class Person{

    private String name;
    private String address;
    public Person(){

    }

    public Person(String name, String address) {
        this.name = name;
        this.address = address;
    }

    @Override
    public String toString() {
        return super.toString();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}


interface JavaNewObject<T extends Person>{
    T create(String name, String address);
}

class testNewClass{
    public static void main(String[] args) {
        JavaNewObject<Person> factory = Person::new;
        Person p = factory.create("小米","山东");
        System.out.println(p.toString());
        /**
         * jdk1.8API包含了很多内建的函数式接口,在老Java中常用到的比如 Comparator或者Runnable
         * 接口,这些接口增加了@FuncationalInterface注解以便能用在lambda接口上
         * JAVA8同时还提供了很多全新的函数式接口来让工作更加方便,有一些接口来自 Google Guava库
         */
        /**
         * Predicate接口只有一个参数 返回boolean类型 该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑
         */
        Predicate<String> predicate = s -> {

            return s.equals("1");
        };
        boolean b = predicate.test("1");
        System.out.println(b);

        Predicate<Person> booleanPredicate = Objects::nonNull;
        System.out.println(booleanPredicate.test(p));
        /**
         * Function接口只有一个参数并且返回一个结果,并附带了一些可以和其他函数组合的默认的方法
         * ::引入静态方法
         */
        // Integer 引入静态 valueOf方法
        Function<String,Integer> function = Integer::valueOf;
        //String 引入静态 length方法
        Function<String,Integer> function1 = String::length;
        String s = "1234";
        Integer length = function1.apply(s);
        System.out.println(length);
        /**
         * Supplier 接口返回任意泛型的值 该接口没有任何参数
         */
        Supplier<String> stringSupplier =String::new;
        stringSupplier.get();
    }
}
